-- 运营活动: 达标竞技


--[[
{
    cmd_id = 1, -- 命令id，用于批量停止、删除活动 
    act_id = 43, -- 活动id (43 元宝转盘)
    act_name = "元宝转盘", -- 活动名称
    act_desc = "活动期间获取经验达到对应档次则可领取丰厚奖励！", -- 活动描述
    beg_time = 1493262000,  -- 活动开始时间(unix timestamp)
    end_time = 1593267430,  -- 活动结束时间(unix timestamp)
    config = -- 配置数据
    {
        everyGoldPerScore = 10,             --充值1元宝多少积分
        everyGoldConsumeScore = 10,         --消费1元宝多少积分
        everyPlayCosumeScore = 1000,        --玩一次转盘消耗多少积分
        saveCount = 50, --保存最多信息
        itemList =  
        {   
            {
                weight = 1,
                icon = 1,
                awards = 
                {
                    { weight = 1, type = 0, id = 508, count = 2,},
                    { weight = 1, type = 0, id = 571, count =30,},
                    { weight = 1, type = 0, id = 563, count = 3,},
                    { weight = 1, type = 0, id = 558, count = 3,},
                    { weight = 1, type = 0, id = 568, count = 3,},
                    { weight = 1, type = 0, id = 524, count = 2,},
                    { weight = 1, type = 0, id = 529, count = 2,},
                    { weight = 1, type = 0, id = 534, count = 2,},
                    { weight = 1, type = 0, id = 539, count = 2,},
                    { weight = 1, type = 0, id = 763, count =10,},
                    { weight = 1, type = 0, id = 509, count = 1,},              
                },
            },
            {
                weight = 1,
                icon = 1,
                awards = 
                {
                    { weight = 1, type = 0, id = 508, count = 2,},
                    { weight = 1, type = 0, id = 571, count =30,},
                    { weight = 1, type = 0, id = 563, count = 3,},
                    { weight = 1, type = 0, id = 558, count = 3,},
                    { weight = 1, type = 0, id = 568, count = 3,},
                    { weight = 1, type = 0, id = 524, count = 2,},
                    { weight = 1, type = 0, id = 529, count = 2,},
                    { weight = 1, type = 0, id = 534, count = 2,},
                    { weight = 1, type = 0, id = 539, count = 2,},
                    { weight = 1, type = 0, id = 763, count =10,},
                    { weight = 1, type = 0, id = 509, count = 1,},              
                },
            },
            {
                weight = 1,
                icon = 1,
                awards = 
                {
                    { weight = 1, type = 0, id = 508, count = 2,},
                    { weight = 1, type = 0, id = 571, count =30,},
                    { weight = 1, type = 0, id = 563, count = 3,},
                    { weight = 1, type = 0, id = 558, count = 3,},
                    { weight = 1, type = 0, id = 568, count = 3,},
                    { weight = 1, type = 0, id = 524, count = 2,},
                    { weight = 1, type = 0, id = 529, count = 2,},
                    { weight = 1, type = 0, id = 534, count = 2,},
                    { weight = 1, type = 0, id = 539, count = 2,},
                    { weight = 1, type = 0, id = 763, count =10,},
                    { weight = 1, type = 0, id = 509, count = 1,},              
                },
            },
            {
                weight = 1,
                icon = 1,
                awards = 
                {
                    { weight = 1, type = 0, id = 508, count = 2,},
                    { weight = 1, type = 0, id = 571, count =30,},
                    { weight = 1, type = 0, id = 563, count = 3,},
                    { weight = 1, type = 0, id = 558, count = 3,},
                    { weight = 1, type = 0, id = 568, count = 3,},
                    { weight = 1, type = 0, id = 524, count = 2,},
                    { weight = 1, type = 0, id = 529, count = 2,},
                    { weight = 1, type = 0, id = 534, count = 2,},
                    { weight = 1, type = 0, id = 539, count = 2,},
                    { weight = 1, type = 0, id = 763, count =10,},
                    { weight = 1, type = 0, id = 509, count = 1,},              
                },
            },
            {
                weight = 1,
                icon = 1,
                awards = 
                {
                    { weight = 1, type = 0, id = 508, count = 2,},
                    { weight = 1, type = 0, id = 571, count =30,},
                    { weight = 1, type = 0, id = 563, count = 3,},
                    { weight = 1, type = 0, id = 558, count = 3,},
                    { weight = 1, type = 0, id = 568, count = 3,},
                    { weight = 1, type = 0, id = 524, count = 2,},
                    { weight = 1, type = 0, id = 529, count = 2,},
                    { weight = 1, type = 0, id = 534, count = 2,},
                    { weight = 1, type = 0, id = 539, count = 2,},
                    { weight = 1, type = 0, id = 763, count =10,},
                    { weight = 1, type = 0, id = 509, count = 1,},              
                },
            },
            {
                weight = 1,
                icon = 1,
                awards = 
                {
                    { weight = 1, type = 0, id = 508, count = 2,},
                    { weight = 1, type = 0, id = 571, count =30,},
                    { weight = 1, type = 0, id = 563, count = 3,},
                    { weight = 1, type = 0, id = 558, count = 3,},
                    { weight = 1, type = 0, id = 568, count = 3,},
                    { weight = 1, type = 0, id = 524, count = 2,},
                    { weight = 1, type = 0, id = 529, count = 2,},
                    { weight = 1, type = 0, id = 534, count = 2,},
                    { weight = 1, type = 0, id = 539, count = 2,},
                    { weight = 1, type = 0, id = 763, count =10,},
                    { weight = 1, type = 0, id = 509, count = 1,},              
                },
            },
        },  
    },
}
]]

-- 检查配置是否正确，正确则返回 0，否则返回错误码
function oper_act_43_check_cfg(cfg)
    if cfg == nil then return 20 end
    
    local config = cfg.config
    if config == nil then return 21 end
    
    if config.itemList == nil then return 23 end
    if type(config.itemList) ~= "table" then return 24 end
    for idx = 1, #config.itemList do
        local dayRewards = config.itemList[idx]
        if dayRewards == nil then return 25 end
        if type(dayRewards) ~= "table" then return 26 end
        if dayRewards.awards == nil then return 27 end
        if type(dayRewards.awards) ~= "table" then return 28 end
        if not oper_act_check_one_award_cfg(dayRewards.awards) then
            return 22
        end 
    end

    return 0
end

-- 安装活动，成功则返回 0，否则返回错误码
function oper_act_43_setup(cfg) 
    return 0
end

-- 卸载活动
function oper_act_43_unsetup(cfg)   
end

-- 活动开始
function oper_act_43_start(cfg)
    local ssVar = System.getStaticVar()
    ssVar.oper_act_43_start = 1
    ssVar.oper_act_43_cmd = cfg.cmd_id
    ssVar.oper_act_43_act = cfg.act_id

    local data = gRankMgr_GetValueByIndx(0, RANK_DEFINE_OPERATION_43, 1)

    local needClearState = true

    local crossDayState = false

    if data then
        local myData = BaseFuc_unserialize(data)
        if myData and myData.cmd_id and myData.cmd_id == cfg.cmd_id and myData.act_id and myData.act_id == cfg.act_id and
            myData.time and cfg.beg_time <= myData.time and  cfg.end_time > myData.time then
            needClearState = false
            local time = System.getSystemTime()
            if myData and myData.mySelfTime and not System.isUnixTimeSameDay(myData.mySelfTime, time) then
                crossDayState = true
            end
        end
    end

    if needClearState or crossDayState then
        gRankMgr_Clear(RANK_DEFINE_OPERATION_43)
        clearOperationWorldData(cfg.act_id)
    end
end

-- 活动结束
function oper_act_43_end(cfg)
    local ssVar = System.getStaticVar()
    ssVar.oper_act_43_start = nil
    ssVar.oper_act_43_cmd = nil
    ssVar.oper_act_43_act = nil

end

-- 打包数据
function oper_act_43_packet_data(sysarg, cfg)
    if not cfg then return end
    local config = cfg.config
    if not config then return end

    local actorid = Actor.getActorId(sysarg)

    local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_43, 1)

    local myData = BaseFuc_unserialize(data)

    if not myData then
        myData = {}
    end

    if not myData.myScore then
        myData.myScore = 0
    end

    local npack = oper_act_alloc_init_data_packet(sysarg, cfg.cmd_id, cfg.act_id)
    if (npack == nil) then
        return
    end

    --print("myData.myScore ="..myData.myScore)
    DataPack.writeInt(npack, myData.myScore)

    local dVar = Actor.getDyanmicVar(sysarg)
    local circle = dVar.oper_act_43_circle or 1
    local index = dVar.oper_act_43_index or 1

    local dataTable, curCicle, curIndex = getOperationWorldData(cfg.act_id, circle, index, config.saveCount)
    dVar.oper_act_43_circle =  curCicle
    dVar.oper_act_43_index =  curIndex
    if dataTable then
        local len = #dataTable
        --print("len ="..len)
        DataPack.writeByte(npack, len)
        for idx = 1, len do
            --print("idx = "..idx)
            DataPack.writeString(npack, dataTable[idx].name)
            DataPack.writeByte(npack, dataTable[idx].type)
            DataPack.writeShort(npack, dataTable[idx].id)
            DataPack.writeInt(npack, dataTable[idx].count)
        end
    else
        --print("len = 0")
        DataPack.writeByte(npack, 0)
    end

    DataPack.flush(npack) 
    
end

-- 操作，返回操作结果，0为成功
function oper_act_43_do(sysarg, cfg, clientPkt)
    if cfg == nil then return end
    
    if cfg.state == nil or cfg.state ~= 1 then -- 不在活动中
        Actor.sendTipmsg(sysarg,Lang.ScriptTips.Operation001, ttFlyTip)
        return
    end
    
    local config = cfg.config
    if config == nil then -- 参数错误
        print("error, oper_act_43_do cfg.config confg error")
        return
    end

    local actorid = Actor.getActorId(sysarg)

    local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_43, 1)

    local myData = BaseFuc_unserialize(data)

    if not myData then
        myData = {}
    end

    if not myData.myScore then
        myData.myScore = 0
    end

    local time = System.getSystemTime()
    if not myData.cmd_id then
        myData.cmd_id = cfg.cmd_id
        myData.act_id = cfg.act_id
        myData.time = time
    end
    myData.mySelfTime = time

    local opType = DataPack.readByte(clientPkt)
    --print("opType ="..opType)
    if opType == 1 then
        if myData.myScore < config.everyPlayCosumeScore then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation059, ttFlyTip)
            return
        elseif Item.getBagEmptyGridCount( sysarg ) <= 0 then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0015, ttFlyTip)
            return
        end

        local dVar = Actor.getDyanmicVar(sysarg)
        if dVar.oper_act_43_reward_index then
            operation_act_43_send_awards(sysarg, cfg)
            dVar.oper_act_43_reward_index = nil
        end

        myData.myScore = myData.myScore - config.everyPlayCosumeScore

        local newData = BaseFuc_serialize(myData)
        gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_43, 1, newData)

        local index, item = GetItemIdxRandExt(config.itemList)

        dVar.oper_act_43_reward_index = index

        local netPack = oper_act_alloc_do_result_packet(sysarg, cfg.cmd_id, cfg.act_id, 0)
        if not netPack then return end
        --print("opType ="..opType)
        --print("index ="..index)
        --print("myData.myScore ="..myData.myScore)
        DataPack.writeByte(netPack, opType) 
        DataPack.writeByte(netPack, index)
        DataPack.writeInt(netPack, myData.myScore) 

    --  DataPack.writeByte(netPack, 1) -- 活动特有参数
        DataPack.flush(netPack)
    elseif opType == 3 then
        if myData.myScore < config.everyPlayCosumeScore * 10 then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation059, ttFlyTip)
            return
        elseif Item.getBagEmptyGridCount( sysarg ) < 10 then
            Actor.sendTipmsg(sysarg, string.format(Lang.ScriptTips.Operation060, 10), ttFlyTip)
            return
        end

        local dVar = Actor.getDyanmicVar(sysarg)
        if dVar.oper_act_43_reward_index then
            operation_act_43_send_awards(sysarg, cfg)
            dVar.oper_act_43_reward_index = nil
        end

        myData.myScore = myData.myScore - config.everyPlayCosumeScore * 10

        local newData = BaseFuc_serialize(myData)
        gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_43, 1, newData)

        local nineAwards = {}
        local index
        local item
        for idx = 1, 9 do
            index, item = GetItemIdxRandExt(config.itemList)
            local awardList = item.awards
            local ii, newItem = GetItemIdxRandExt(awardList)

            if newItem.broadcast and newItem.broadcast > 0 then
                local noticeStr = string.format(Lang.ScriptTips.Operation134, Actor.getName(sysarg), cfg.act_name, Item.getItemLinkMsg(newItem.id), newItem.count)
                System.broadcastTipmsg(noticeStr, ttScreenCenter + ttChatWindow)
            end

            table.insert(nineAwards, newItem)
            local saveData = {}
            saveData.name = Actor.getName(sysarg)
            saveData.type = newItem.type
            saveData.id = newItem.id
            saveData.count = newItem.count
            setOperationWorldData(cfg.act_id, saveData, config.saveCount)

        end

        if IsBagGridEnough(sysarg, nineAwards) then
            Awards.Give(sysarg,nineAwards,LogIds.OperationLogId043,Lang.LogTips.Operation043)
        else
            local actorid = Actor.getActorId(sysarg)
            local title = Lang.ScriptTips.Operation057
            local content = Lang.ScriptTips.Operation058
            local sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
            local vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
            Awards.GiveToMailById(actorid, nineAwards, title, content, LogIds.OperationLogId043, Lang.LogTips.Operation043, vocation, sex)
        end 
        
        index, item = GetItemIdxRandExt(config.itemList)
        dVar.oper_act_43_reward_index = index

        local netPack = oper_act_alloc_do_result_packet(sysarg, cfg.cmd_id, cfg.act_id, 0)
        if not netPack then return end
        --print("opType ="..opType)
        --print("index ="..index)
        --print("myData.myScore ="..myData.myScore)
        DataPack.writeByte(netPack, opType) 
        DataPack.writeByte(netPack, index)
        DataPack.writeInt(netPack, myData.myScore) 

    --  DataPack.writeByte(netPack, 1) -- 活动特有参数
        DataPack.flush(netPack)
    elseif opType == 2 then
        local dVar = Actor.getDyanmicVar(sysarg)
        if not dVar.oper_act_43_reward_index then
            Actor.sendTipmsg(sysarg, Lang.ScriptTips.Operation005, ttFlyTip)
            return
        end

        operation_act_43_send_awards(sysarg, cfg)

        dVar.oper_act_43_reward_index = nil

        oper_act_43_packet_data(sysarg, cfg)
    end
end

--下线
function oper_act_43_logout(sysarg)
    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_43_start then
        return
    end
    if not ssVar.oper_act_43_cmd then
        return
    end
    if not ssVar.oper_act_43_act then
        return
    end
    
    local cfg = get_oper_act_cfg(ssVar.oper_act_43_cmd, ssVar.oper_act_43_act)
    if not cfg then
        return
    end

    local config = cfg.config
    if not config then
        return
    end 
    operation_act_43_send_awards(sysarg, cfg)
end

function operation_act_43_send_awards(sysarg, cfg)
    if not cfg then
        return
    end

    local config = cfg.config
    if not config then
        return
    end 
    local dVar = Actor.getDyanmicVar(sysarg)
    if dVar.oper_act_43_reward_index then
        if dVar.oper_act_43_reward_index <= #config.itemList then
            local awardList = config.itemList[dVar.oper_act_43_reward_index].awards
            local index, item = GetItemIdxRandExt(awardList)
            if IsBagGridEnough(sysarg, {item}) then
                Awards.Give(sysarg,{item},LogIds.OperationLogId043,Lang.LogTips.Operation043)
            else
                local actorid = Actor.getActorId(sysarg)
                local title = Lang.ScriptTips.Operation057
                local content = Lang.ScriptTips.Operation058
                local sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
                local vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
                Awards.GiveToMailById(actorid, {item}, title, content, LogIds.OperationLogId043, Lang.LogTips.Operation043, vocation, sex)
            end 
            if item.broadcast and item.broadcast > 0 then
                local noticeStr = string.format(Lang.ScriptTips.Operation134, Actor.getName(sysarg), cfg.act_name, Item.getItemLinkMsg(item.id), item.count)
                System.broadcastTipmsg(noticeStr, ttScreenCenter + ttChatWindow)
            end
            local saveData = {}
            saveData.name = Actor.getName(sysarg)
            saveData.type = item.type
            saveData.id = item.id
            saveData.count = item.count
            setOperationWorldData(cfg.act_id, saveData, config.saveCount)
        end
    end
end

function oper_act_43_withdrawyuanbao(sysarg, value)
    if value <= 0 then
        return
    end

    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_43_start then
        return
    end
    if not ssVar.oper_act_43_cmd then
        return
    end
    if not ssVar.oper_act_43_act then
        return
    end
    
    local cfg = get_oper_act_cfg(ssVar.oper_act_43_cmd, ssVar.oper_act_43_act)
    if not cfg then
        return
    end

    local config = cfg.config
    if not config then
        return
    end 

    value = config.everyGoldPerScore * value

    oper_act_43_get_value_arrive(sysarg, value)
end

function oper_act_43_consumeyuanbao(sysarg, value)
    if value <= 0 then
        return
    end

    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_43_start then
        return
    end
    if not ssVar.oper_act_43_cmd then
        return
    end
    if not ssVar.oper_act_43_act then
        return
    end
    
    local cfg = get_oper_act_cfg(ssVar.oper_act_43_cmd, ssVar.oper_act_43_act)
    if not cfg then
        return
    end

    local config = cfg.config
    if not config then
        return
    end 

    value = config.everyGoldConsumeScore * value

    oper_act_43_get_value_arrive(sysarg, value)
end

-- 跨天
function oper_act_43_new_day_arrive(act_id) 

    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_43_start then
        return
    end
    if not ssVar.oper_act_43_cmd then
        return
    end
    if not ssVar.oper_act_43_act then
        return
    end
    local cfg = get_oper_act_cfg(ssVar.oper_act_43_cmd, ssVar.oper_act_43_act)
    if not cfg then
        return
    end
    local config = cfg.config
    if not config then return end

    gRankMgr_Clear(RANK_DEFINE_OPERATION_43)

     local players = LuaHelp.getAllActorList()
    if players then 
        for k, v in ipairs(players) do  
            oper_act_43_packet_data(sysarg)
        end
    end
end

function oper_act_43_get_value_arrive(sysarg, value)
    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_43_start then
        return
    end
    if not ssVar.oper_act_43_cmd then
        return
    end
    if not ssVar.oper_act_43_act then
        return
    end
    
    local cfg = get_oper_act_cfg(ssVar.oper_act_43_cmd, ssVar.oper_act_43_act)
    if not cfg then
        return
    end

    local config = cfg.config
    if not config then
        return
    end 

    local actorid = Actor.getActorId(sysarg)

    local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_43, 1)

    local myData = BaseFuc_unserialize(data)

    if not myData then
        myData = {}
    end

    if not myData.myScore then
        myData.myScore = 0
    end

    myData.myScore = myData.myScore + value
    
    local time = System.getSystemTime()
    if not myData.cmd_id then
        myData.cmd_id = cfg.cmd_id
        myData.act_id = cfg.act_id
        myData.time = time
    end
    myData.mySelfTime = time
    local newData = BaseFuc_serialize(myData)
    gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_43, 1, newData)

    
    oper_act_43_packet_data(sysarg, cfg)
end